package cn.twh.wall.config;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import cn.twh.wall.util.OgnlUtil;
import ognl.OgnlException;

@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "wall", ignoreUnknownFields = true)
public class WallConfig {
	private static final Logger logger = Logger.getLogger(WallConfig.class);
	/** 
	 * 默认失败率 0-100
	 */
	private int failRate;
	
	/** 
	 * 默认超时率 0-100
	 */
	private int timeOutRate;
	
	/** 
	 * 接口失败率 样例：
	 * interfaceFailRate: 
	 *     api: 50
	 */
	private Map<String,Integer> interfaceFailRate = new HashMap<>();
	
	/** 
	 * 接口失败率 样例：
	 * interfaceTimeOutRate: 
	 *     api: 50
	 */
	private Map<String,Integer> interfaceTimeOutRate = new HashMap<>();
	
	/** 
	 * 接口失败标志 样例：
	 * interfaceFailFlag:
	 *     api: 
	 *         ognl-key1:
	 *             - val1
	 *             - val2
	 */
	private Map<String,Map<String,Set<String>>> interfaceFailFlag = new HashMap<>();
	
	/** 
	 * 接口超时标志 样例：
	 * interfaceTimeOutFlag:
	 *     api: 
	 *         ognl-key1:
	 *             - val1
	 *             - val2
	 */
	private Map<String,Map<String,Set<String>>> interfaceTimeOutFlag = new HashMap<>();
	/**
	 * 压测模式：保留，暂未使用
	 * true 会去掉大部分耗时操作并使用缓存，如果在写挡板逻辑请设定为false.
	 * false 默认false
	 */
	private boolean pressureMode=false;
	public void setFailRate(int failRate) {
		this.failRate = failRate;
	}

	public void setTimeOutRate(int timeOutRate) {
		this.timeOutRate = timeOutRate;
	}

	public void setInterfaceFailRate(Map<String, Integer> interfaceFailRate) {
		this.interfaceFailRate = interfaceFailRate;
	}

	public void setInterfaceTimeOutRate(Map<String, Integer> interfaceTimeOutRate) {
		this.interfaceTimeOutRate = interfaceTimeOutRate;
	}

	public void setInterfaceFailFlag(Map<String, Map<String,Set<String>>> interfaceFailFlag) {
		this.interfaceFailFlag = interfaceFailFlag;
	}

	public void setInterfaceTimeOutFlag(Map<String, Map<String,Set<String>>> interfaceTimeOutFlag) {
		this.interfaceTimeOutFlag = interfaceTimeOutFlag;
	}
	/**
	 * 获取api的失败权重
	 * @param api 请求接口
	 * @return 接口失败率 当接口特别指定失败率不存在时使用默认失败率
	 */
	public int getFaildRate(String api) {
		if(interfaceFailRate.containsKey(api)) {
			return interfaceFailRate.get(api);
		}else {
			return failRate;
		}
	}
	
	/**
	 * 获取api的超时权重
	 * @param api 请求接口
	 * @return 接口超时率 当接口特别指定超时率不存在时使用默认超时率
	 */
	public int getTimeOutRate(String api) {
		if(interfaceTimeOutRate.containsKey(api)) {
			return interfaceTimeOutRate.get(api);
		}else {
			return timeOutRate;
		}
	}
	
	/**
	 * 是否包含失败标志
	 * @param data 请求报文
	 * @param api 接口
	 * @return 是否包含 true 包含 false 不包含
	 */
	public boolean containsFaildFlag(Map<?,?> data,String api) {
		return containsFlag(data,api,interfaceFailFlag);
	}
	
	/**
	 * 是否包含超时标志
	 * @param data 请求报文
	 * @param api 接口
	 * @return 是否包含 true 包含 false 不包含
	 */
	public boolean containsTimeOutFlag(Map<?,?> data,String api) {
		return containsFlag(data,api,interfaceTimeOutFlag);
	}
	/**
	 * 判断是否包含flag
	 * @param data 请求报文
	 * @param api 接口
	 * @return 是否包含 true 包含 false 不包含
	 */
	private boolean containsFlag(Map<?,?> data,String api,Map<String,Map<String,Set<String>>> interfaceFlag) {
		if(interfaceFlag.containsKey(api)) {
			Map<String,Set<String>> flags=interfaceFlag.get(api);
			Iterator<Entry<String, Set<String>>> it =flags.entrySet().iterator();
			while(it.hasNext()) {
				Entry<String, Set<String>> item=it.next();
				try {
					String val=OgnlUtil.getValue(data, item.getKey());
					if(item.getValue().contains(val)) {
						// 超时响应匹配
						return true;
					}
				} catch (OgnlException e) {
					logger.error("application properties interfaceTimeOutFlag ognl illegal："+item.getKey(),e);
					return false;
				}
			}
		}
		return false;
	}
	
	public int getFailRate() {
		return failRate;
	}

	public int getTimeOutRate() {
		return timeOutRate;
	}

	public Map<String, Integer> getInterfaceFailRate() {
		return interfaceFailRate;
	}

	public Map<String, Integer> getInterfaceTimeOutRate() {
		return interfaceTimeOutRate;
	}

	public Map<String, Map<String,Set<String>>> getInterfaceFailFlag() {
		return interfaceFailFlag;
	}

	public Map<String, Map<String,Set<String>>> getInterfaceTimeOutFlag() {
		return interfaceTimeOutFlag;
	}

	public boolean isPressureMode() {
		return pressureMode;
	}

	public void setPressureMode(boolean pressureMode) {
		this.pressureMode = pressureMode;
	}
}
